package cn.akira.domain.strategy.service.raffle;

import cn.akira.domain.strategy.model.entity.RaffleAwardEntity;
import cn.akira.domain.strategy.model.entity.RaffleFactorEntity;
import cn.akira.domain.strategy.model.entity.StrategyAwardEntity;
import cn.akira.domain.strategy.repository.IStrategyRepository;
import cn.akira.domain.strategy.service.rule.chain.factory.DefaultChainFactory;
import cn.akira.domain.strategy.service.rule.tree.factory.DefaultTreeFactory;
import cn.akira.types.enums.ResponseCode;
import cn.akira.types.exception.AppException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.Date;

/**
 * @author fjl95
 * @date 2025/5/12
 * @description 抽奖策略抽象类-提供模版
 */
@Slf4j
public abstract class AbstractRaffleStrategy implements IRaffleStrategy{

    protected IStrategyRepository strategyRepository;


    protected DefaultChainFactory defaultChainFactory;

    protected DefaultTreeFactory defaultTreeFactory;

    public AbstractRaffleStrategy(IStrategyRepository strategyRepository, DefaultChainFactory defaultChainFactory,DefaultTreeFactory defaultTreeFactory) {
        this.strategyRepository = strategyRepository;
        this.defaultChainFactory = defaultChainFactory;
        this.defaultTreeFactory = defaultTreeFactory;
    }



    @Override
    public RaffleAwardEntity performRaffle(RaffleFactorEntity raffleFactorEntity) {
        //1.获取抽奖动作的输入参数userId,strategtId
        String userId = raffleFactorEntity.getUserId();
        Long strategyId = raffleFactorEntity.getStrategyId();
        if (strategyId == null || StringUtils.isBlank(userId)) {
            throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(),ResponseCode.ILLEGAL_PARAMETER.getInfo());
        }

        //责任链抽奖前规则校验
        DefaultChainFactory.StrategyAwardVO chainStrategyAwardVO = raffleLogicChain(userId, strategyId);
        //如果是黑名单，权重等被接管，直接返回抽奖结果（这里有个前提，是我设置的权重抽奖必中奖，不会参与后续的库存判断）
        if (!chainStrategyAwardVO.getLogicModel().equals("default")) {
            return buildRaffleAwardEntity(strategyId,chainStrategyAwardVO.getAwardId(),null);

        }
        log.info("中奖奖品：{}",chainStrategyAwardVO.getAwardId());

        //规则树抽奖中规则校验[锁，库存，兜底]
        DefaultTreeFactory.StrategyAwardVO treeStrategyAwardVO = raffleLogicTree(userId,strategyId,chainStrategyAwardVO.getAwardId(),raffleFactorEntity.getEndDateTime());


        return buildRaffleAwardEntity(strategyId,treeStrategyAwardVO.getAwardId(),treeStrategyAwardVO.getAwardRuleValue());
    }

    private RaffleAwardEntity buildRaffleAwardEntity(Long strategyId, Integer awardId,String awardConfig) {
        StrategyAwardEntity strategyAward = strategyRepository.queryStrategyAwardEntity(strategyId,awardId);
        return RaffleAwardEntity.builder()
                .awardTitle(strategyAward.getAwardTitle())
                .awardId(awardId)
                .awardConfig(awardConfig)
                .sort(strategyAward.getSort())
                .build();
    }

    /**
     * 抽奖计算，责任链抽象方法
     */
    public abstract DefaultChainFactory.StrategyAwardVO raffleLogicChain(String userId,Long strategyId);
    /**
     * 抽奖结果过滤，规则树抽象方法
     */
    public abstract DefaultTreeFactory.StrategyAwardVO raffleLogicTree(String userId,Long strategyId,Integer awardId);
    /**
     * 抽奖结果过滤，规则树抽象方法
     */
    public abstract DefaultTreeFactory.StrategyAwardVO raffleLogicTree(String userId, Long strategyId, Integer awardId, Date endDateTime);

}

